package main

import (
	"context"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	_ "github.com/go-sql-driver/mysql" // IMPORTANT
)

type User struct {
	Id   int
	Name string `orm:"size(100)"` // 执行生成表字段的 schema
}

type Post struct {
	Id    int    `orm:"auto"`
	Title string `orm:"size(100)"`
	User  *User  `orm:"rel(fk)"`
}

func init() {
	// set default db
	orm.RegisterDataBase("default", "mysql", "root:123456@tcp(localhost:3306)/go-sql")

	// register model
	orm.RegisterModel(new(User), new(Post))

	// create table
	orm.RunSyncdb("default", false, true) // 非强制，但是输出详细信息
}

func main() {
	orm.Debug = true // 设置 Debug

	o := orm.NewOrm()
	user := User{Name: "pedro"}

	// insert
	id, err := o.Insert(&user)
	fmt.Printf("ID: %d, ERR: %v\n", id, err)

	// update
	user.Name = "jerry"
	num, err := o.Update(&user)
	fmt.Printf("NUM: %d, ERR: %v\n", num, err)

	// read one
	u := User{Id: user.Id}
	err = o.Read(&u)
	fmt.Printf("ERR: %v\n", err)

	// delete
	//num, err = o.Delete(&u)
	//fmt.Printf("NUM: %d, ERR: %v\n", num, err)

	// 插入 posts 数据
	p1 := Post{
		Title: "p1",
		User:  &u,
	}
	p2 := Post{
		Title: "p2",
		User:  &u,
	}
	p3 := Post{
		Title: "p3",
		User:  &u,
	}
	// insert posts
	num, err = o.InsertMulti(3, []Post{p1, p2, p3})
	fmt.Printf("NUM: %d, ERR: %v\n", num, err)

	// 关联查询
	var posts []*Post
	qs := o.QueryTable("post")
	num, err = qs.Filter("User__name", "jerry").All(&posts)
	fmt.Printf("NUM: %d, ERR: %v\n", num, err)

	// SQL 原生查询
	var maps []orm.Params
	num, err = o.Raw("SELECT * FROM user").Values(&maps)
	for _, term := range maps {
		fmt.Println(term["id"], ":", term["name"])
	}

	// 事务处理，闭包方式
	err = o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
		mike := User{
			Name: "mike",
		}
		_, e := txOrm.Insert(&mike)
		// 如果这个地方的 e 不为 nil，那么闭包的上层会自动 Rollback
		return e
	})
	fmt.Printf("ERR: %v\n", err)
	// 事务处理，声明方式
	txOrm, err := o.Begin()
	peter := User{
		Name: "peter",
	}
	num, err = txOrm.Insert(&peter)
	fmt.Printf("NUM: %d, ERR: %v\n", num, err)
	if err != nil {
		txOrm.Rollback()
	} else {
		txOrm.Commit()
	}
}
